package com.wjx.zk;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class ZookeeperTest implements Watcher {
    private static ZooKeeper zk;
    static Stat stat = new Stat();

    public static void main(String[] args) throws IOException, InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        zk = new ZooKeeper("192.168.11.128:2182,192.168.11.128:2183,192.168.11.128:2184", 5000, new ZookeeperTest());
        System.out.println("state: " + zk.getState() + " sessionId: " + zk.getSessionId() + " pwd: " + new String(zk.getSessionPasswd(), "utf-8"));

        createSync();
        createASync();

        getSync();
        getASync();

        getData();

        setData();

        exists();

        countDownLatch.await();
    }

    private static void createSync() {
        try {
//            String path = zk.create("/test1", "t1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
//            System.out.println("create path1 :"+path);
            String path1 = zk.create("/test1/test2", "t1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
            System.out.println("create path2 :" + path1);
            String path2 = zk.create("/test1/test3", "t1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void getSync() {
        try {
            List<String> children = zk.getChildren("/test1", true);
            System.out.println(children);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private static void getASync() {
        try {
            zk.getChildren("/test1", true, new getCallBack(), " is ctx");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void createASync() {
        try {
            zk.create("/test2", "t1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL, new CallBack(), "test1 call back");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void getData() {
        try {
            System.out.println("get data " + new String(zk.getData("/test1", true, stat), "utf-8"));
            System.out.println("stat " + stat.getCzxid() + " " + stat.getMzxid() + " " + stat.getVersion());
            zk.setData("/test1", "ss".getBytes(), -1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void setData() {
        try {
            Stat s = zk.setData("/test1", "ss1".getBytes(), -1);
            System.out.println("stat1: " + s.getVersion());
            s = zk.setData("/test1", "ss1".getBytes(), s.getVersion());
            System.out.println("stat2: " + s.getVersion());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void exists() {
        try {
            zk.exists("/test3", true);
            zk.create("/test3", "test".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
            zk.setData("/test3", "test".getBytes(), -1);
            zk.delete("/test3", -1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    static class CallBack implements AsyncCallback.StringCallback {

        /**
         * @param rc 0 ：创建成功，4：客户端已断开，110：节点已存在，112：会话已过期
         */
        @Override
        public void processResult(int rc, String path, Object ctx, String name) {
            System.out.println("callback :  rc: " + rc + " path: " + path + " ctx: " + ctx + " name: " + name);
        }
    }

    static class getCallBack implements AsyncCallback.Children2Callback {

        @Override
        public void processResult(int rc, String path, Object ctx, List<String> children, Stat stat) {
            System.out.println("get children call back  rc: " + rc + " path: " + path + " ctx: " + ctx + " children: " + children + " stat: " + stat);
        }
    }

    @Override
    public void process(WatchedEvent watchedEvent) {
        System.out.println("receive event: " + watchedEvent);
        try {
            if (watchedEvent.getType().equals(Event.EventType.NodeChildrenChanged)) {
                List<String> children = zk.getChildren(watchedEvent.getPath(), true);
                System.out.println("reGet child " + children);
            } else if (watchedEvent.getType().equals(Event.EventType.NodeDataChanged)) {
                System.out.println("reGet data " + new String(zk.getData(watchedEvent.getPath(), true, stat)));
                System.out.println("reGet stat " + stat.getCzxid() + " " + stat.getMzxid() + " " + stat.getVersion());
            } else if (watchedEvent.getType().equals(Event.EventType.NodeCreated)) {
                System.out.println("craete node" + watchedEvent.getPath());
                zk.exists(watchedEvent.getPath(), true);
            } else if (watchedEvent.getType().equals(Event.EventType.NodeDeleted)) {
                System.out.println("delete node" + watchedEvent.getPath());
                zk.exists(watchedEvent.getPath(), true);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
